/* --- math-function-modi if math_func_helper doesn't use function-parameters */
#define MODE_ADD simplehash('a','d') /* x = x+y (2) */
#define MODE_DEC simplehash('d','e') /* x = x-1 (1) */
#define MODE_DIV simplehash('d','i') /* x = x/y (2) */
#define MODE_INC simplehash('i','n') /* x = x+1 (1) */
#define MODE_MOD simplehash('m','o') /* x = x%y (2) */
#define MODE_MUL simplehash('m','u') /* x = x*y (2) */
#define MODE_NEG simplehash('n','e') /* x = -x (1) */
#define MODE_NOT simplehash('n','o') /* x = ~x (1) */
#define MODE_SUB simplehash('s','u') /* x = x-y (2) */
#ifndef MAXIA
#define MAXIA 5
#endif
#define OP_SUB 1 /* the values are used for priorities, too */
#define OP_ADD 2
#define OP_DIV 3
#define OP_MOD 4
#define OP_MUL 5
/**************************************
Interne Prototypes
**************************************/
/**************************************
Impementation
**************************************/
/*
*!
*! math functions offer the user a simple calculator,
*! which recognizes +,-,*,/,%,(,);
*! 2 numbers must be separated with one operator,
*! !!each operator must be surrounded with whitespaces!!
*! (there are no unique +/- operators allowed, if they are
*! not part of a number, so "-1" is allowed, "(- 1)" is not!)
*!
*! so each expression has an inequal number of subexpressions -
*! x+1 values and x operators with x in N
*! there should not be more than MAXIA (== 5)
*! expressions on one level (simply use brackets)
*! ( that is in fact no problem, as on any evaluation
*! we try to shorten our results due to operator prorities,
*! and as long as there are only 4 operators used, we do
*! normally not run out of space
*! e.g.:> set abc 0 add abc (1 * 2 + 3 * 4 / 5 - 6) title $abc
*! => 1 => 1* => 1*2 => 1*2+ [-> 2+]
*! => 2+3 => 2+3* => 2+3*4 => 2+3*4/ [-> 2+12/]
*! => 2+12/5 => 2+12/5- [-> 2+2-] [-> 4-] => 4-6
*! == -2
*!
*/
static
long domathop (long a1, char op, long a2)
{
switch (op)
{
case OP_ADD:
return (a1 + a2);
case OP_SUB:
return (a1 - a2);
case OP_MUL:
return (a1 * a2);
case OP_DIV:
return (a1 / a2);
case OP_MOD:
return (a1 % a2);
default:
error ("undefined mathoperator");
return (0);
} /* switch */
} /* domathop */
static
char getmathop (char * str)
{
if (!str)
{
return(0);
} /* if */
switch (*str)
{
case '+':
return (OP_ADD);
case '-':
return (OP_SUB);
case '*':
return (OP_MUL);
case '/':
return (OP_DIV);
case '%':
return (OP_MOD);
default:
error ("unknown operator\n%s", str);
return(0);
} /* switch */
} /* getmathop */
/* static */
long getmathresult (char* expr)
{
long values[MAXIA];
char funcs [MAXIA];
char * str = expr;
int i;
char * checker;
char * aux2 = NULL;
char * dummy = NULL;
char quote = 0;
/* --------- erstes argument muss immer existieren */
if (!expr)
{
error ("empty expression\n(input NIL)");
return(0);
} /* if */
if (is_number(expr))
{
return(atoi(expr));
} /* if */
checker = (UBYTE *)breakout(&str, "e, &aux2);
if (!checker)
{
#if 0
if (aux2) { free (aux2); aux2 = NULL; } /* if */ /* seems senseless */
#endif
error ("empty expression\n(breakout NIL)");
return(0);
} /* if */
/* PATCH_NULL [07 Apr 1993] : BUGFIX >>> */
/* now we are testing : 1. result word starts w/ alpha, 2. word was NOT multiword (AND is nonnumber), 3. word is NOT quoted (AND is not number) */
if (isalpha(checker[0]) || ((str == NULL || *str == 0) && (quote == 0))) { /* should be better : check up to the first space, if there is a non-digit */
if (aux2)
free(aux2);
error ("non-number to math-function");
return (0);
} /* if */
/* PATCH_NULL [07 Apr 1993] : BUGFIX <<< */
values[0] = getmathresult ( checker );
if (aux2)
{
free (aux2);
aux2 = NULL;
} /* if */
i = 0;
while (!globalflags.Abortcommand && str && ( 1/* first checking here */ ))
{
/* --------- operator holen - better put that line into the while-condition */